#!/usr/bin/python
# Sample console appliation serving as sensor data receiver and distributor.
# Uses a default combination of filters found in the filters_graphics
# subdirectory.
# Two devices are supported. An N95 on port 9617 and an Android G1 on
# port 9618. The data of the devices is merged and sent together to
# one receiving application (which in general may not be useful).
# To allow differentiation a device-id is inserted.

import sys, time
import threading
from Sensor import Sensor, UDPSender
import filters_graphics as fg

common_filters = [fg.tapshake5,
                  fg.graphicscontrol,
                  fg.nonlinearxy]

sendhost = "localhost"
sendport = 9642

def add_id(block, id):
    block[0]["devid"] = id
    return block

def show_packet(packet):
    print packet

class MergeSender(object):
    "a sink to merge many streams into one sender"
    def __init__(self, sender):
        self.lock = threading.Lock()
        self.sender = sender
    def __call__(self, packet):
        try:
            self.lock.acquire()
            self.sender(packet)
            self.lock.release()
        except Exception, data:
            pass # http://bugs.python.org/issue7194
        finally:
            if self.lock.locked():
                try:
                    self.lock.release()
                except: # may release unlocked lock?
                    # http://bugs.python.org/issue7194
                    pass


if __name__ == '__main__':
    print " -v verbose"
    print "adding n95(9617), g1(9618), n97(9619)"
    sensorn95 = Sensor(9617)
    sensorn95.register_filter(fg.n95normalize)
    sensorn95.register_filter(lambda block: add_id(block, "n95"))
    sensorg1 = Sensor(9618)
    sensorg1.register_filter(fg.androidg1normalize)
    sensorg1.register_filter(lambda block: add_id(block, "g1"))
    sensorn97 = Sensor(9619)
    sensorn97.register_filter(fg.n97normalize)
    sensorn97.register_filter(lambda block:add_id(block, "n97"))
    for f in common_filters:
        sensorn95.register_filter(f)
        sensorg1.register_filter(f)
        sensorn97.register_filter(f)
    # reduce rate at the end, otherwise we might miss key events...
    sensorn95.register_filter(fg.reducerate)
    sensorg1.register_filter(fg.reducerate)
    sensorn97.register_filter(fg.reducerate)
    if "-v" in sys.argv:
        sensorn95.register_sink(show_packet)
        sensorg1.register_sink(show_packet)
        sensorn97.register_sink(show_packet)
    sender = UDPSender(sendhost, sendport)
    merger = MergeSender(sender)
    sensorn95.register_sink(merger)
    sensorg1.register_sink(merger)
    sensorn97.register_sink(merger)
    sensorn95.start_receiving()
    sensorg1.start_receiving()
    sensorn97.start_receiving()
    try:
        time.sleep(2**30) # sleep long!
    except KeyboardInterrupt:
        print "stopping"
    sensorn95.stop_receiving()
    sensorg1.stop_receiving()
    sensorn97.stop_receiving()
    
